package com.manager.user.module.service;

import com.manager.commons.Constant;
import com.manager.commons.base.DataGrid;
import com.manager.commons.mybatis.dao.GenericDao;
import com.manager.commons.mybatis.service.GenericService;
import com.manager.commons.utils.DateUtil;
import com.manager.commons.utils.FileUtils;
import com.manager.commons.utils.StringUtil;
import com.manager.commons.utils.UUIDUtil;
import com.manager.core.web.json.AjaxJson;
import com.manager.user.module.dao.GenFilesDao;
import com.manager.user.module.dao.GenUserDao;
import com.manager.user.module.dao.UserOrganizationDao;
import com.manager.user.module.entity.*;
import com.manager.user.module.entity.view.FileInfoView;
import com.manager.user.module.entity.view.FileUserPath;
import com.manager.user.utils.FileSizeFormatter;
import com.manager.user.utils.MediaInfoUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;

import static com.manager.user.utils.MediaInfoUtils.*;


/**
 * GenUserService
 * 用户表
 *
 * @author manager
 * @version 1.0
 */
@Service
public class GenUserService extends GenericService<GenUser> {

    @Autowired
    private GenUserDao jdbcDao;

    @Autowired
    private UserOrganizationDao userOrganizationDao;

    @Autowired
    private GenFilesDao filesDao;


    @Override
    public GenericDao<GenUser> getDao() {
        return jdbcDao;
    }


    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public AjaxJson addFile(String userId, String pid, MultipartFile file, Map<String, Object> map) throws Exception {
        Integer isEdit = jdbcDao.querEditPermission(map);
        AjaxJson ajaxJson = new AjaxJson();
        ajaxJson.setMsg("上传失败");
        if (isEdit != null && isEdit == 1) {
            try {

                String uuid = UUIDUtil.getInstance().getUUID();
                String fileName = file.getOriginalFilename();
                HashMap<String, Object> params = new HashMap<String, Object>() {{
                    put("pid", pid);
                    put("name", fileName);
                }};
                Integer n = filesDao.findModelName(params);
                if (n == null || n == 0) {
                    //查询父级文件目录
                    GenFiles pf = filesDao.findModelPath(params);
                    //如果pid不能为空，id不能以pid开头，如果以pid开头则说明是根目录
                    if (StringUtil.isEmpty(pid) || file.getSize() <= 0 || StringUtil.isEmpty(fileName) || pf == null) {
                        ajaxJson.setMsg("文件信息错误");
                        return ajaxJson;
                    }
                    PlatformParameter parameter = getUploadBean();
                    String pPath = parameter.getValue_vc() + parameter.getDescription();
                    String fileExt = FileUtils.getFileExt(fileName);
                    //源文件保存路径
                    String path = pf.getLocalPath();
                    String pathName = path + "/" + fileName;
                    //缩略图文件路径
                    String thumbnailPath = THUMBNAIL_PATH + "/" + uuid + ".webp";
                    FileUtils.createFolder(pPath + THUMBNAIL_PATH);
                    FileUtils.createFolder(pPath + ROOT_PATH + pf.getLocalPath());
                    File newFile = new File(pPath + ROOT_PATH + pf.getLocalPath(), fileName);
                    String fileCompletePath = pPath + ROOT_PATH + pathName;
                    //保存文件
                    file.transferTo(newFile);
                    GenFiles fileInfo = new GenFiles();
                    fileInfo.setId(uuid);
                    fileInfo.setPid(pid);
                    fileInfo.setCreator(userId);
                    fileInfo.setFileExt(fileExt);
                    fileInfo.setName(fileName);
                    fileInfo.setPath(path);
                    fileInfo.setFileSize(file.getSize());
                    fileInfo.setFileSizeName(FileSizeFormatter.format(fileInfo.getFileSize()));
                    fileInfo.setLevelId(pf.getLevelId() + "-" + uuid);
                    //文件为图片，且文件大于3M进行压缩
                    if (MediaInfoUtils.isImageFile(fileExt)) {
                        System.out.println("读取图片信息");
                        fileInfo.setResolution(MediaInfoUtils.getImageResolution(newFile));
                        System.out.println("分辨率读取成功");
                        fileInfo.setResolutionTitle("图片尺寸");
                        fileInfo.setType("jpg");
                        //创建压缩文件
                        fileInfo.setThumb(thumbnailPath);
                        System.out.println("缩率图开始读取" + System.currentTimeMillis());
                        MediaInfoUtils.ImageThumbnail(fileCompletePath, pPath + fileInfo.getThumb());
                        System.out.println("缩率图创建成功");
                    } else if (MediaInfoUtils.isVideoFile(fileExt)) {
                        fileInfo.setThumb(thumbnailPath);
                        fileInfo.setResolutionTitle("分辨率");
                        fileInfo.setType("mp4");
                        MediaInfoUtils.VideoThumbnail(fileInfo, fileCompletePath, pPath + fileInfo.getThumb());
                    } else if (MediaInfoUtils.isAudioFile(fileExt)) {
                        fileInfo.setType("mp3");
                        fileInfo.setDuration(MediaInfoUtils.getAudioDuration(fileCompletePath));
                    } else {
                        if (fileExt.equalsIgnoreCase("xlsx")) {
                            fileInfo.setType("xls");
                        } else {
                            fileInfo.setType(MediaInfoUtils.iaArchiveOrDocumnet(fileExt));
                        }

                    }
                    int f = filesDao.insert(fileInfo);
                    if (f > 0) {
                        ajaxJson.setCode(1);
                        ajaxJson.setMsg("上传成功");
                    }
                } else {
                    ajaxJson.setMsg("文件重复");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new Exception(e);
            }
        } else {
            ajaxJson.setMsg("您没有操作权限，请联系管理员");
        }
        return ajaxJson;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public AjaxJson addFolder(Map<String, Object> map) throws Exception {
        Integer isEdit = jdbcDao.querEditPermission(map);
        AjaxJson ajaxJson = new AjaxJson();
        if (isEdit != null && isEdit == 1) {
            ajaxJson.setMsg("添加失败");
            String id = UUIDUtil.getInstance().getUUID();
            String pid = getParamsString(map, "pid");
            //如果pid不能为空，id不能以pid开头，如果以pid开头则说明是根目录
            if (StringUtil.isEmpty(pid) || pid.startsWith("pid")) {
                ajaxJson.setMsg("请先选择目录");
                return ajaxJson;
            }

            String name = getParamsString(map, "name");
            if (StringUtil.isNotEmpty(name)) {
                Integer n = filesDao.findModelName(map);
                //判断名字是否重复
                if (n == null || n == 0) {//名称没有重复
                    //查询父级文件目录
                    GenFiles pf = filesDao.findModelPath(map);
                    if (pf != null) {
                        String pPath = getUploadPath();
                        GenFiles gf = new GenFiles();
                        gf.setId(id);
                        gf.setPid(pid);
                        gf.setName(name);
                        gf.setCreator(getCreator(map));
                        gf.setType(Constant.FileType.FOLDER.getEcode());
                        gf.setLevelId(pf.getLevelId() + "-" + id);
                        gf.setPath(pf.getPath() + "/" + pf.getName());
                        int f = filesDao.insert(gf);
                        boolean c = FileUtils.createFilesFolder(pPath + gf.getPath() + "/" + gf.getName());
                        if (f == 1 && c) {
                            ajaxJson.setCode(f);
                            ajaxJson.setMsg("添加成功");
                            gf.setCreateTime(DateUtil.currentDate(DateUtil.DATETIME_FORMAR_STRING_yyyyMMddHHmmss));
                            gf.setModifyTime(gf.getCreateTime());
                            ajaxJson.setData(gf);
                        } else {
                            throw new Exception("创建创建失败");
                        }
                    } else {
                        ajaxJson.setMsg("目录信息查询错误");
                    }
                } else {
                    ajaxJson.setMsg("文件夹名称重复，请重新输入");
                }
            } else {
                ajaxJson.setMsg("请输入文件夹名称");
            }

        } else {
            ajaxJson.setMsg("您没有操作权限，请联系管理员");
        }
        return ajaxJson;
    }

    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public AjaxJson updateName(Map<String, Object> params) throws Exception {
        Integer isEdit = jdbcDao.querEditPermission(params);
        AjaxJson ajaxJson = new AjaxJson();
        if (isEdit != null && isEdit == 1) {
            try {
                String name = getParamsString(params, "name");
                String _id = getParamsString(params, "_id");
                if (StringUtil.isEmpty(_id)) {
                    ajaxJson.setMsg("文件夹信息错误");
                } else if (StringUtil.isEmpty(name)) {
                    ajaxJson.setMsg("文件夹名称不能为空");
                } else {
                    Integer n = filesDao.findModelName(params);
                    //判断名字是否重复
                    if (n == null || n == 0) {//名称没有重复
                        GenFiles genFiles = filesDao.findModel(_id);
                        String pPath = getUploadPath();
                        if (genFiles != null && !StringUtil.isEmpty(genFiles.getName())) {
                            if (genFiles.getName().equals(name)) {
                                ajaxJson.setCode(1);
                                ajaxJson.setMsg("修改成功");
                            } else {
                                int f = filesDao.updateMap(params);
                                //修改前的文件路径
                                String path = pPath + genFiles.getPath() + "/" + genFiles.getName();
                                //修改命名之后的文件路径
                                String nPath = pPath + genFiles.getPath() + "/" + name;
                                if (genFiles.getType().equals(Constant.FileType.FOLDER.getEcode())) {
                                    f += filesDao.updateFileName(path, nPath);
                                }
                                boolean rename = false;
                                //修改文件名称
                                if (f > 0) rename = FileUtils.renameWithNIO(path, nPath);
                                if (f > 0 && rename) {
                                    ajaxJson.setCode(1);
                                    ajaxJson.setMsg("重命名成功");
                                    genFiles.setModifyTime(DateUtil.currentDate(DateUtil.DATETIME_FORMAR_STRING_yyyyMMddHHmmss));
                                    ajaxJson.setData(genFiles);
                                } else {
                                    throw new Exception("文件重命名失败");
                                }
                            }

                        } else {
                            ajaxJson.setMsg("未查询到文件夹信息");
                        }
                    } else {
                        ajaxJson.setMsg("文件夹名称重复，请重新输入");
                    }

                }

            } catch (Exception e) {
                throw e;
            }
        } else {
            ajaxJson.setMsg("您没有操作权限，请联系管理员");
        }
        return ajaxJson;
    }

    /**
     * 删除
     *
     * @param params
     * @return
     */
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public AjaxJson myDelete(Map<String, Object> params) throws Exception {
        Integer isEdit = jdbcDao.querEditPermission(params);
        if (isEdit != null && isEdit == 1) {
            try {
                if (null != params) {
                    String idstr = getParamsString(params, "ids");
                    String[] ids = idstr.split(",");
                    Map<String, Object> idSet = new HashMap<String, Object>() {{
                        put("_ids", ids);
                    }};
                    String pPath = getUploadPath();
                    List<GenFiles> filesList = filesDao.querFileInfos(idSet);
                    boolean result = false;
                    int f = 0;
                    for (GenFiles genFiles : filesList) {
                        f = filesDao.deleteFiles(genFiles.getLevelId());
                        if (f > 0) {
                            result = FileUtils.delete(pPath + genFiles.getLocalPath());
                            if (!result) {
                                break;
                            }
                        } else {
                            break;
                        }

                    }
                    if (f > 0 && result) {
                        return new AjaxJson(1, "删除成功");
                    } else {
                        throw new Exception("删除失败");
                    }
                }
                return new AjaxJson("参数错误");
            } catch (Exception e) {
                throw e;
            }
        } else {
            return new AjaxJson("您没有操作权限，请联系管理员");
        }

    }

    /**
     * 分页查询
     *
     * @param params
     * @return
     */
    public DataGrid queryPageFiles(Map<String, Object> params) {
        try {
            if (null != params) {
                String pid = getParamsString(params, "pid");
                //pid代表原有目录  gid 代表中间添加了企业目录
                if (pid.indexOf(",") > 0 || pid.startsWith("pid")) {
                    String tag = "pid";
                    if (pid.startsWith("gid")) tag = "gid";
                    String p = pid.replace(tag, "");
                    List<String> ids = new ArrayList<>();
                    if (pid.indexOf(",") > 0) {
                        ids.addAll(Arrays.asList(p.split(",")));
                    } else {
                        ids.add(p);
                    }
                    params.put("_ids", ids);
                }
                if (pid.startsWith("gids")) {
                    int count = filesDao.countMapGids(params);
                    List<FileInfoView> list = filesDao.queryFileMapGids(params);
                    return new DataGrid(count, list);
                } else if (pid.startsWith("gid")) {
                    params.put("gid", pid.replace("gid", ""));
                    int count = filesDao.countMapGid(params);
                    List<FileInfoView> list = filesDao.queryFileMapGid(params);
                    return new DataGrid(count, list);
                } else {
                    int count = filesDao.countMap(params);
                    List<FileInfoView> list = filesDao.queryFileMap(params);
                    return new DataGrid(count, list);
                }

            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return new DataGrid(0, new ArrayList<GenFiles>());
    }

    /**
     * 分页查询
     *
     * @param params
     * @return
     */
    public DataGrid queryPageSearchFiles(Map<String, Object> params) {
        try {
            if (null != params) {
                int count = filesDao.countSearch(params);
                List<FileInfoView> list = filesDao.queryFileSearch(params);
                return new DataGrid(count, list);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return new DataGrid(0, new ArrayList<GenFiles>());
    }

    public List<FolderInfo> fileFolder(Map<String, Object> map) {
        List<FolderInfo> list = new ArrayList<>();
        map.put("type", Constant.FileType.FOLDER.getEcode());
        List<FolderInfo> folders = filesDao.queryFolder(map);
        if (folders != null && !folders.isEmpty()) {
            list.addAll(folders);
        }
        return buildTree(list, false);
    }

    public List<FolderInfo> folderTree(Map<String, Object> params) {
        List<FolderInfo> list = new ArrayList<>();
        //根据当前用户信息，查询所属组织
        List<FileUserPath> paths = filesDao.queryFileUser(params);
        FolderInfo folderInfo = new FolderInfo();
        folderInfo.setName("位置");
        folderInfo.setLast(true);
        folderInfo.setExpanded(true);
        folderInfo.setSelected(true);
        Map<String, FolderInfo> map = new HashMap<>();
        List<String> ids = new ArrayList<>();
        List<String> pids = new ArrayList<>();
        for (FileUserPath path : paths) {
            FolderInfo folder;
            if (map.containsKey(path.getGeName())) {
                folder = map.get(path.getGeName());
            } else {
                folder = new FolderInfo();
                folder.setId("gid" + path.getGeId());
                folder.setName(path.getGeName());
                ids.add(path.getGeId());
            }
            pids.add(path.getGfId());
            FolderInfo folderChild = new FolderInfo();
            folderChild.setId(path.getGfId());
            folderChild.setName(path.getGfName());
            folderChild.setChildrenCount(path.getChildrenCount());
            folderChild.setCreateTime(path.getCreateTime());
            folderChild.setModifyTime(path.getModifyTime());
            folderChild.setParentId(folder.getId());
            folder.getChildren().add(folderChild);
            map.put(path.getGeName(), folder);
        }
        folderInfo.setId("gids" + String.join(",", ids));
        map.forEach((key, value) -> {
            if (map.size() == 1) {
                folderInfo.setId("pid" + String.join(",", pids));
                value.setParentId(folderInfo.getId());
                value.setChildrenCount(value.getChildren().size());
                for (FolderInfo folderChild : value.getChildren()) {
                    folderChild.setParentId(folderInfo.getId());
                }
                folderInfo.getChildren().addAll(value.getChildren());
            } else {
                value.setParentId(folderInfo.getId());
                value.setChildrenCount(value.getChildren().size());
                folderInfo.getChildren().add(value);
            }

        });

        list.add(folderInfo);


        return list;
    }

    // 将节点列表转换为树形结构
    public static List<FolderInfo> buildTree(List<FolderInfo> nodes, boolean isSelect) {
        // 使用 Map 存储节点，键为节点 ID，值为节点对象
        Map<String, FolderInfo> nodeMap = new HashMap<>();
        // 根节点列表
        List<FolderInfo> rootNodes = new ArrayList<>();

        // 第一步：将所有节点放入 Map 中
        for (FolderInfo node : nodes) {
            nodeMap.put(node.getId(), node);
        }
        // 第二步：构建树结构
        for (FolderInfo node : nodes) {
            String parentId = node.getParentId();
            // 如果 parentId 为 0 或者在 Map 中找不到对应的父节点，则该节点为根节点
            if (StringUtil.isEmpty(parentId) || !nodeMap.containsKey(parentId)) {
                if (StringUtil.isEmpty(parentId)) node.setParentId("0");
                rootNodes.add(node);
            } else {
                // 否则，将该节点添加到其父节点的子节点列表中
                FolderInfo parentNode = nodeMap.get(parentId);
                parentNode.addChild(node);
            }
        }
        if (isSelect) {
            FolderInfo folderInfo = rootNodes.get(0);
            folderInfo.setSelected(true);
            folderInfo.setExpanded(true);
        }
        return rootNodes;
    }

    public PlatformParameter getBaseParameter(String code) {
        return userOrganizationDao.getBaseParameter(code);
    }

    public String getUploadPath() {
        PlatformParameter parameter = getUploadBean();
        return parameter.getValue_vc() + parameter.getDescription() + ROOT_PATH;
    }

    public PlatformParameter getUploadBean() {
        return getBaseParameter("UPLOAD_PATH");
    }

    public Integer querEditPermission(Map<String, Object> map) {
        return jdbcDao.querEditPermission(map);
    }

    public Integer querDownPermission(Map<String, Object> map) {
        return jdbcDao.querDownPermission(map);
    }

}
